package handler

import (
	"bytes"
	"fmt"
	"io"
	"iptv_server/v3/src/settings"
	"iptv_server/v3/v2_src/handler/middleware"
	"iptv_server/v3/v2_src/utils"
	"iptv_server/v3/v2_src/utils/cache"
	vodpush "iptv_server/v3/v2_src/vod_push"
	"net/http"
	"os"
	"path"
	"strconv"
	"sync"
	"time"
)

//	public static final String apiUrl_listremotes = "http://gate." + MyServerDomain + ":81/cgi-bin/tvbox_box1.sh?do=listremotes";
//
// http://tv1.server.lan:9966/api/tvbox_box1?do=listremotes&addme

// const (
// 	url_getJson = "/api/tvboxpush/postme"
// )

// var (
// 	rooturl string = "http://v3.tv.server.lan:19999"
// )

func InitPushCenter(mux *http.ServeMux, middles ...middleware.MiddleWare) {
	center := &pushCenter{
		store: cache.NewCache[[]byte]("tv address", time.Hour*1),
		dir:   settings.Dir_MORE,
	}

	// mkdir .
	os.MkdirAll(path.Join(settings.Dir_StaticFile, settings.Dir_MORE), 0755)

	// if len(settings.SiteDomain) > 10 {
	// 	rooturl = settings.SiteDomain
	// }

	h := middleware.ApplyMiddles(center, middles...)
	mux.Handle("/api/tvboxpush", h)
	mux.Handle("/api/tvboxpush/", h)
	// mux.Handle(url_getJson, h)
	// mux.Handle(url_getJson+"/", h)

	mux.HandleFunc("/api/tvboxpush/dir2", handlerDir2)
	mux.HandleFunc("/api/tvboxpush/dir2/", handlerDir2)

	h2 := middleware.ApplyMiddles(&ended{}, middles...)
	mux.Handle("/api/tvboxpush/ended", h2)
	mux.Handle("/api/tvboxpush/ended/", h2)

}

func handlerDir2(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err == nil {
		name := r.Form.Get("name")
		is_del := r.Form.Has("del")
		if vodpush.VodToDir2(name, is_del) {
			w.WriteHeader(http.StatusOK)
			w.Write([]byte("ok"))
		} else {
			w.Write([]byte("failed"))
		}
	}
}

type ended struct {
}

func (h *ended) ServeHTTP(w http.ResponseWriter, r *http.Request) {

}

type pushCenter struct {
	current int
	sync.Mutex
	// tmp     string
	dir   string
	store *cache.Cache[[]byte]
}

func (h *pushCenter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	postTo := ""
	is_get := true
	if err := r.ParseForm(); err == nil {
		postTo = r.Form.Get("dst")
		is_get = r.Form.Has("get")
		// fmt.Printf("postTo: %v\n", postTo)
		// fmt.Printf("is_get: %v\n", is_get)
	}

	if is_get || r.Method == http.MethodGet {
		h.handlerGet(w, r)
		return
	}

	if r.Method == http.MethodPost {
		h.handlerPost(w, r, postTo)
	}
}

func (h *pushCenter) handlerPost(w http.ResponseWriter, r *http.Request, who string) {
	var contentType string

	push := func(bs []byte) {
		//  http://box.domain/pushvod
		if len(who) > 0 {
			resp, err := http.Post(who, contentType, bytes.NewReader(bs))
			resp.Body.Close()
			if err != nil {
				w.Write([]byte("push_target: failed!\n"))
			} else {
				w.Write([]byte("push_target: success!\n"))
			}
		}
	}

	contentType = r.Header.Get(utils.HeaderKeyContentType)
	var bs []byte
	if contentType == utils.ContentTypeJson {
		// process json, 并存到server
		bs = h.processJsonData(r)
	} else {
		//other: pushed = url
		// 不存到server
		bs = h.processOtherData(r)
		contentType = utils.ContentTypePlainTextUTF8
	}

	if len(bs) > 0 {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("push:OK\n"))
		push(bs)
	}

}

func (h *pushCenter) processOtherData(r *http.Request) []byte {
	bs, err := io.ReadAll(r.Body)
	if err != nil {
		return nil
	}

	content := string(bs)
	if utils.IsHttpUrl(content) {
		return bs
	} else {
		return nil
	}
}

func (h *pushCenter) processJsonData(r *http.Request) []byte {
	// vp := vodpush.New("http://v3.tv.server.lan:19999", "/data/files", "more_and_more")
	vp := vodpush.New(h.dir)

	bs, err := io.ReadAll(r.Body)
	// fmt.Println(1)
	if err != nil {
		fmt.Printf("err: %v\n", err)
		return nil
	}
	// fmt.Println(2)
	err = vp.Unmarshal(bs)
	if err != nil {
		fmt.Printf("Unmarshal err: %v\n", err)
		return nil
	}
	// fmt.Println(3)
	if err := vp.DownloadPic(); err != nil {
		fmt.Printf("Download_pic err: %v\n", err)
	}
	bs, err = vp.Marshal()
	if err != nil {
		fmt.Printf("marshal err: %v\n", err)
		return nil
	}
	// fmt.Printf("json Marshaled:\n%s\n", string(bs))
	// fmt.Println(4)
	h.add(bs)

	return bs
}

func (h *pushCenter) handlerGet(w http.ResponseWriter, r *http.Request) {
	_ = r.ParseForm()
	index := r.Form.Get("index")
	i := 0
	if len(index) > 0 {
		if ii, err := strconv.Atoi(index); err == nil {
			i = ii
		}
	}

	data, _, ok := h.getData(i)
	// data, ok := h.tmp, len(h.tmp) > 0
	w.Header().Set("__push_center__", "yes")
	if ok {
		w.Header().Set(utils.HeaderKeyContentType, utils.ContentTypeJson)
		w.WriteHeader(http.StatusOK)
		w.Write(data)
		// fmt.Printf("json data: %v\n", string(data))
		return
	}
	fmt.Printf("json data len==0\n")

	w.WriteHeader(http.StatusNotFound)
}

// -> []byte,expired,ok
func (h *pushCenter) getData(i int) ([]byte, bool, bool) {
	//get lastest  index=i
	// h.tmp = s
	i = max(h.current-i, 0)
	return h.store.Get(strconv.Itoa(i))
}

func (h *pushCenter) add(bs []byte) {
	// TODO 限制总容量

	h.Lock()
	defer h.Unlock()

	// h.tmp = s
	h.current++ // 这样 key就从 "1" 开始了
	h.store.Save(strconv.Itoa(h.current), bs)
	for k, v := range h.store.GetAll() {
		fmt.Printf("k: %v\n", k)
		fmt.Printf("v: %v\n", string(v))
	}
}

// func (h *pushCenter) String() string {
// 	// all := red.store.GetAll()
// 	// builder := &strings.Builder{}
// 	// for k, v := range all {
// 	// 	builder.WriteString(k)
// 	// 	builder.WriteString(fmt.Sprintf(" timestamp: %d\n", v.Unix()))
// 	// }
// 	// return builder.String()
// 	return ""
// }

//  /api/tvboxpush

//http://localhost:9966/api/tvboxpush/postme/
